Chapter 2: `Diffraction <CH2_00-Diffraction.ipynb>`__


Fourier Transform Laboratory

Real and Reciprocal Lattice

Download

Open In Colab

part of

`MSE672: Introduction to Transmission Electron Microscopy <../_MSE672_Intro_TEM.ipynb>`__

by Gerd Duscher, Spring 2021

Microscopy Facilities Joint Institute of Advanced Materials Materials Science & Engineering The University of Tennessee, Knoxville

Background and methods to analysis and quantification of data acquired with transmission electron microscopes.

Import numerical and plotting python packages

Check Installed Packages

[2]:
import sys
from pkg_resources import get_distribution, DistributionNotFound

def test_package(package_name):
    """Test if package exists and returns version or -1"""
    try:
        version = get_distribution(package_name).version
    except (DistributionNotFound, ImportError) as err:
        version = '-1'
    return version

# Colab setup ------------------
if 'google.colab' in sys.modules:
    !pip install pyTEMlib -q
# pyTEMlib setup ------------------
else:
    if test_package('pyTEMlib') < '0.2021.1.9':
        print('installing pyTEMlib')
        !{sys.executable} -m pip install  --upgrade pyTEMlib -q
# ------------------------------
print('done')
done

Load the plotting and figure packages

[3]:
import sys
if 'google.colab' in sys.modules:
    %pylab --no-import-all inline
else:
    %pylab --no-import-all notebook
Populating the interactive namespace from numpy and matplotlib

Fourier Transform Input

[4]:
length = 256
half = int(length/2)
x_axis  = np.arange(length)-half
real_space = np.zeros(length)
real_space[half] = 0.
real_space[half-10] = 0.
real_space[half+10-1] = 0.
real_space[half-120] = 1.
real_space[half+120] = 0.


for i in range(int(length/4)):
#    if i % 2:
#        real_space[i*4] = 1.
#    else:
#        real_space[i*4] = .5
    pass

plt.figure()
plt.plot(x_axis, real_space);

Fourier Transform Output

[8]:
real_space = np.zeros(length)
real_space[half] = 0.
real_space[half-10] = 0.
real_space[half+10-1] = 0.
real_space[half-127] = 0.
real_space[half+127] = 1.

fourier_space = np.fft.fft(real_space)

fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True)

ax1.plot(x_axis, real_space.real , label='real')
ax1.plot(x_axis, real_space.imag , label='imag')
ax1.legend()
ax1.title.set_text('Real Space')

ax2.plot(x_axis, fourier_space.real , label='real')
ax2.plot(x_axis, fourier_space.imag , label='imag')
ax2.legend()
ax2.title.set_text('Reciprocal Space');

Inverse Fourier Transform

[10]:
fourier_space.imag = 0
real_space_2 = np.fft.ifft(fourier_space)

fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, dpi=160)
ax1.plot(x_axis, fourier_space.real , label='real')
ax1.plot(x_axis, fourier_space.imag , label='imag')
ax1.title.set_text('Reciprocal Space')
ax2.plot(x_axis, real_space_2.real , label='real')
ax2.plot(x_axis, real_space_2.imag , label='imag')
ax2.title.set_text('Real Space')
ax2.legend();

And now in 3D

The Fourier Transform of the sample shape is a major contributer to the possible excitation error

[153]:

from skimage import measure
from mpl_toolkits.mplot3d import Axes3D

##################
# Make a disk
##################
s = 32
vol = np.zeros((32*2,32*2,32*2))

# Make one circle
circle = np.zeros((64,64))
for x in range (-32,32):
    for y in range(-32,32):
        if x**2+y**2 < s**2-100:
            circle[x+32,y+32]=1
# Make a disk by copying the full circle
thickness = 10
for z in range(int(s-thickness/2),int(s+thickness/2)):
    vol[:,:,z] = circle

# Make a cube
s = 32
#vol = np.zeros((32*2,32*2,32*2))
width = 20
vol[s-width:s+width,s-width:s+width,s-width:s+width] = 1

# Fourier Transform in 3D
ft = np.fft.fftshift(np.fft.fftn(vol))

#Make surfaces from volume
verts, faces, _, _ = measure.marching_cubes_lewiner(np.absolute(ft), 400.)
rverts, rfaces, _, _ = measure.marching_cubes_lewiner(vol, 0)


fig = plt.figure(figsize=(10, 5))
ax1 = fig.add_subplot(121, projection='3d')
ax1.plot_trisurf(rverts[:, 0], rverts[:,1], rfaces, rverts[:, 2], lw=1)
ax1.set_xlim(0, 64)
ax1.set_ylim(0, 64)
ax1.set_zlim(0, 64)
ax1.set_title('Real Space')

ax2 = fig.add_subplot(122, projection='3d')
ax2.plot_trisurf(verts[:, 0], verts[:,1], faces, verts[:, 2], lw=1)
ax2.set_xlim(0, 64)
ax2.set_ylim(0, 64)
ax2.set_zlim(0, 64)
ax2.set_title('Reciprocal Space');

Conclusions

Fourier transform of symmetric function do not have a imaginary component.

Imaginary Fourier components are often associated with absorption. Why?

Chapter 2: Diffraction

List of Content: Front

Lwave-v8.gif Lwave-Red-2.gif

[ ]: